#include <stdio.h>    // FILE must be provided before including jpeglib.h
#include <stdlib.h>   // malloc, free
#include <stddef.h>   // size_t (although typically included by stdio/stdlib, explicitly including it is safer)
#include <stdint.h>   // uint8_t
#include <setjmp.h>   // for error handling

// Then include the project headers and jpeglib
#include "htf_jpeg_decoder.h"
#include <jpeglib.h>

// Error handling structure
struct my_error_mgr {
    struct jpeg_error_mgr pub;
    jmp_buf setjmp_buffer;
};

typedef struct my_error_mgr* my_error_ptr;

static void my_error_exit(j_common_ptr cinfo) {
    my_error_ptr myerr = (my_error_ptr)cinfo->err;
    (*cinfo->err->output_message)(cinfo);
    longjmp(myerr->setjmp_buffer, 1);
}

int htf_jpeg_decode_to_rgb(const uint8_t* jpeg_data, size_t size,
                           uint8_t** out_rgb, int* width, int* height) {
    if (!jpeg_data || !out_rgb || !width || !height || size == 0) {
        return -1;
    }

    struct jpeg_decompress_struct cinfo;
    struct my_error_mgr jerr;

    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;

    if (setjmp(jerr.setjmp_buffer)) {
        jpeg_destroy_decompress(&cinfo);
        return -2;
    }

    jpeg_create_decompress(&cinfo);
    jpeg_mem_src(&cinfo, (unsigned char*)jpeg_data, (unsigned long)size);

    jpeg_read_header(&cinfo, TRUE);
    cinfo.out_color_space = JCS_RGB;
    jpeg_start_decompress(&cinfo);

    *width = (int)cinfo.output_width;
    *height = (int)cinfo.output_height;
    int row_stride = cinfo.output_width * 3; // RGB: 3 bytes per pixel

    size_t total_size = (size_t)row_stride * cinfo.output_height;
    *out_rgb = (uint8_t*)malloc(total_size);
    if (!*out_rgb) {
        jpeg_destroy_decompress(&cinfo);
        return -3;
    }

    // Decode line by line
    while (cinfo.output_scanline < cinfo.output_height) {
        uint8_t* row_ptr = *out_rgb + (cinfo.output_scanline) * row_stride;
        JSAMPARRAY buffer = &row_ptr;
        jpeg_read_scanlines(&cinfo, buffer, 1);
    }

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    return 0;
}